home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char rcs_id[] = "$Header:$";
- #endif lint
-
- #include <stdio.h>
- #include "glassert.h"
- #include "memoryio.h"
- #include "grasp.h"
-
-
- extern ImageStruct *readimage (FILE *fp, FilenameStruct *dirent, int filetype);
-
-
- #define INT_TYPE long
-
-
- #define FOPEN(filename, mode) mopen (filename, mode)
- #define FCLOSE(stream) mclose (stream)
- #define FSEEK(stream, offset, whence) mseek (stream, offset, whence)
- #define FTELL(stream) mtell (stream)
- #define FREAD(array, size, numitems, stream) mread (array, size, numitems, stream)
- #define GETC(stream) mgetc (stream)
- #define PUTC(c, stream) mputc (c, stream)
-
-
- #define fatal(message) error ("%s: %s\n", message)
-
-
- typedef int bool;
-
- typedef struct codestruct
- {
- struct codestruct *prefix;
- unsigned char first,suffix;
-
- } codetype;
-
- static
- int datasize, codesize, codemask,
- clear, eoi,
- globalbits;
-
- static
- unsigned int
- *interleavetable = (unsigned int *) NULL;
-
- static
- unsigned int
- screenwidth,
- screenheight,
- xx,yy,
- left,width,
- top,height,
- colorbits;
-
- static
- bool
- global,
- interleaved;
-
- static
- codetype
- *codetable;
-
- static
- char
- colortable[256][3],
- globalmap[256][3];
-
- static
- unsigned int
- rThresh;
- static
- unsigned int
- rNormalize;
- static
- unsigned int
- rColors;
- static
- float
- rGamma;
-
- #define RALL_COLORS 0
- #define RGRAYSCALE 1
- #define RRED 2
- #define RGREEN 3
- #define RBLUE 4
-
- static
- int
- red[256], green[256], blue[256];
-
- static unsigned int lastY = 0;
- static char *pOut = (char *) NULL;
- static long offsetP = 0L;
-
- static MemoryFile *tempfile = (MemoryFile *) NULL;
- static MemoryFile *infile = (MemoryFile *) NULL;
-
-
- #define PUTIPIXEL(x, y, val) \
- { \
- register unsigned int thisY = interleavetable[y]; \
- \
- if (lastY != thisY) \
- { \
- register long delta; \
- \
- delta = (long) (width * (thisY - lastY - 1)); \
- if (delta /* != 0L */) \
- FSEEK (tempfile, delta, 1); \
- \
- lastY = thisY; \
- } \
- \
- PUTC (val, tempfile); \
- }
-
- #define PUTPIXEL(x, y, val) PUTC(val, tempfile)
-
-
- void
- outcode (p)
-
- register codetype *p;
- {
- int x, y;
-
-
- assert (p);
-
- if (p->prefix)
- outcode (p->prefix);
-
- if (interleaved)
- {
- PUTIPIXEL (xx, yy, p->suffix);
- }
- else
- {
- PUTPIXEL (xx, yy, p->suffix);
- }
-
- if (++xx > width - 1)
- {
- xx = 0;
- yy++;
-
- if (yy > height - 1)
- yy = 0;
- }
- }
-
-
- void
- process (code)
-
- register int code;
- {
- static unsigned int avail = 0;
- static int oldcode = 0;
- register codetype *p;
-
-
- if (code == clear) {
- codesize = datasize + 1;
- codemask = (1 << codesize) - 1;
- avail = clear + 2;
- oldcode = -1;
- }
- else if (code < avail) {
- outcode(&codetable[code]);
- if (oldcode != -1) {
- p = &codetable[avail++];
- p->prefix = &codetable[oldcode];
- p->first = p->prefix->first;
- p->suffix = codetable[code].first;
- if ((avail & codemask) == 0 && avail < 4096L) {
- codesize++;
- codemask += avail;
- }
- }
- oldcode = code;
- } else if (code == avail && oldcode != -1) {
- p = &codetable[avail++];
- p->prefix = &codetable[oldcode];
- p->first = p->prefix->first;
- p->suffix = p->first;
- outcode(p);
- if ((avail & codemask) == 0 && avail < 4096L) {
- codesize++;
- codemask += avail;
- }
- oldcode = code;
- } else {
- char message[256];
-
- sprintf (message,
- "Illegal code (0x%x > 0x%lx)) in raster data @ 0x%lx.",
- code, avail, FTELL (infile) - 1L);
- if (imverbose) {
- sprintf (message + strlen (message),
- "\n Next pixel to write @ (%d, %d).\n", xx, yy);
- }
- fatal (message);
- }
- }
-
-
- void
- readraster (width, height)
-
- unsigned int width, height;
- {
- unsigned char
- buf[255];
- register INT_TYPE bits=0;
- register unsigned INT_TYPE count,datum=0;
- register unsigned char *ch;
- register unsigned int code;
- register unsigned INT_TYPE readCount;
-
-
- datasize = (unsigned int) GETC (infile);
-
- clear = 1 << datasize;
- eoi = clear+1;
- codesize = datasize + 1;
- codemask = (1 << codesize) - 1;
-
- codetable = (codetype *) malloc (4096L * (unsigned long) sizeof(codetype));
- if (!codetable) fatal ("Not enough memory for code table");
- for (code = 0; code < clear + 2; code++)
- {
- codetable[code].prefix = (codetype*)NULL;
- codetable[code].first = code;
- codetable[code].suffix = code;
- }
- for (count = GETC (infile);
- count > 0;
- count = GETC (infile))
- {
- if ((readCount = (unsigned INT_TYPE) FREAD (buf, (size_t)1, (size_t) count, infile))
- != count)
- break;
- for (ch=buf; count-- > 0; ch++) {
- datum += (unsigned INT_TYPE) *ch << bits;
- bits += 8;
- while (bits >= codesize) {
- code = datum & codemask;
- datum >>= codesize;
- bits -= codesize;
-
- if (code == eoi) goto exitloop; /* This kludge put in
- because some GIF files
- aren't standard */
- process(code);
- }
- }
- }
-
- {
- char message[256];
-
- sprintf (message,
- "Code block length %d had only %d bytes @ 0x%lx.",
- count, readCount, FTELL (infile) - 1L);
- if (imverbose) {
- sprintf (message + strlen (message),
- "\n Next pixel to write @ (%d, %d).\n", xx, yy);
- }
- fatal (message);
- }
-
- exitloop:
- if (imverbose &&
- yy != height &&
- xx != 0 && yy != 0)
- fprintf (stderr,
- " Premature EOI code: next pixel @ (%d, %d).\n",
- xx, yy);
-
- free (codetable);
- }
-
-
- /* Read image information (position, size, local color map, etc.). */
-
- static void
- myreadimage (void)
-
- {
- unsigned char
- buf[9];
-
- bool
- local;
-
- char
- localmap[256][3];
-
- int localbits;
-
- register
- row;
-
- register i;
- void initcolors (char colortable[256][3], char colormap[256][3], int ncolors);
-
-
- FSEEK (tempfile, 0L, 0);
- lastY = 0L;
-
- FREAD (buf, (size_t)1, (size_t)9, infile);
- left = buf[0] + (buf[1] << 8);
- top = buf[2] + (buf[3] << 8);
- width = buf[4] + (buf[5] << 8);
- height = buf[6] + (buf[7] << 8);
- if (imverbose)
- {
- fprintf (stderr, " Image origin at (%d, %d).\n", left, top);
- fprintf (stderr, " Image width and height are (%d, %d).\n",
- width, height);
- }
-
- if (tempfile /* != (MemoryFile *) NULL */)
- (void) FCLOSE (tempfile);
-
- if ((tempfile = FOPEN ("raster", "wb")) == (MemoryFile *) NULL ||
- FSEEK (tempfile, (size_t) width * (size_t) height - 1L, SEEK_CUR)
- /* != 0 */)
- {
- (void) FCLOSE (tempfile);
- (void) FCLOSE (infile);
- error ("%s: not enough memory for raster image.\n", NULL);
- return;
- }
-
- (void) FSEEK (tempfile, 0L, SEEK_SET);
-
- local = buf[8] & 0x80;
- interleaved = buf[8] & 0x40;
- if (local)
- {
- long startMap = FTELL (infile);
-
- localbits = (buf[8] & 0x7) + 1;
- FREAD(localmap, (size_t)3, (size_t)(1<<localbits), infile);
- if (imverbose) {
- fprintf (stderr,
- " Local color map (%d colors) from 0x%lx to 0x%lx.\n",
- 1 << localbits, startMap, FTELL (infile) - 1L);
- }
- colorbits = localbits;
- initcolors(colortable, localmap, 1<<localbits);
- } else if (global) {
- colorbits = globalbits;
- initcolors(colortable, (char **) globalmap, 1<<globalbits);
- } else {
- fatal ("No colormap present for image");
- }
- if (imverbose) {
- fprintf (stderr, " Image is %sinterleaved.\n",
- interleaved ? "" : "not ");
- }
- if (interleaved)
- {
- interleavetable = (unsigned int *) malloc((unsigned long) (height * sizeof(int)));
-
- if (!interleavetable)
- fatal ("Not enough memory for interleave table");
- row = 0;
- for (i = 0; i < height; i += 8)
- interleavetable[row++] = i;
- for (i = 4; i < height; i += 8)
- interleavetable[row++] = i;
- for (i = 2; i < height; i += 4)
- interleavetable[row++] = i;
- for (i = 1; i < height; i += 2)
- interleavetable[row++] = i;
- }
-
- readraster (width, height);
-
- if (interleavetable /* != (unsigned int *) NULL */)
- {
- free ((char *) interleavetable);
- interleavetable = (unsigned int *) NULL;
- }
- }
-
-
- /* Read a GIF extension block (and do nothing with it). */
-
- void
- readextension ()
-
- {
- unsigned char
- code,
- count;
-
- char
- buf[255];
-
- code = GETC(infile);
- while (count = GETC(infile))
- FREAD (buf, (size_t)1,(size_t)count,infile);
- }
-
-
- static int
- checksignature ()
-
- {
- char buf[6];
- int retVal = 0;
-
-
- FREAD (buf, 1, 6, infile);
-
- if (strncmp (buf,"GIF",3))
- retVal = -1;
- if (strncmp (buf + 3,"87a",3))
- retVal = -2;
-
- return retVal;
- }
-
-
- static void
- readscreen (void)
-
- {
- unsigned char buf[7];
-
- xx = yy = 0;
- FREAD (buf,1,7,infile);
- screenwidth = buf[0] + (buf[1] << 8);
- screenheight = buf[2] + (buf[3] << 8);
- if (imverbose) {
- fprintf (stderr, "Screen width and height are (%d, %d).\n",
- screenwidth, screenheight);
- }
-
- global = buf[4] & 0x80;
- if (global) {
- long startGlobal = FTELL (infile);
-
- globalbits = (buf[4] & 0x07) + 1;
- FREAD (globalmap, 3, 1 << globalbits, infile);
-
- if (imverbose) {
- fprintf (stderr,
- "Global color map (%d colors) from 0x%lx to 0x%lx.\n",
- 1 << globalbits, startGlobal, FTELL (infile) - 1L);
- }
- }
- else {
- if (imverbose) {
- fprintf (stderr, "No global color map.\n");
- }
- }
- }
-
-
- #define MAX_INDEX(val) \
- { \
- maxColor = (maxColor > (val)) ? maxColor : (val); \
- }
-
-
- #define MAX_COLOR(r, g, b) \
- { \
- MAX_INDEX (r); \
- MAX_INDEX (g); \
- MAX_INDEX (b); \
- }
-
-
- #define NORMALIZE_INDEX(val) \
- { \
- (val) = ((val) * rNormalize + maxColor2) / maxColor; \
- if ((val) > 255) \
- (val) = 255; \
- }
-
-
- #define NORMALIZE_COLOR(r, g, b) \
- { \
- NORMALIZE_INDEX (r); \
- NORMALIZE_INDEX (g); \
- NORMALIZE_INDEX (b); \
- }
-
-
- #define GRAYSCALE_COLOR(r, g, b) \
- { \
- register int lum = 299 * (r) + 587 * (g) + 114 * (b); \
- register int grayvalue = (lum + 500) / 1000; \
- \
- if (grayvalue > 255) \
- grayvalue = 255; \
- \
- (r) = grayvalue; \
- (g) = grayvalue; \
- (b) = grayvalue; \
- }
-
-
- #define GAMMA_INDEX(val) \
- { \
- (val) = gamma[(val)]; \
- }
-
-
- #define GAMMA_CORRECT(r, g, b) \
- { \
- GAMMA_INDEX (r); \
- GAMMA_INDEX (g); \
- GAMMA_INDEX (b); \
- }
-
-
- static void
- process_loop (void)
-
- {
- int quit = FALSE;
- int imageNum = 0;
- long startImage = 0L;
-
-
- do
- {
- unsigned char ch;
-
-
- ch = (unsigned char) GETC (infile);
-
- switch (ch)
- {
- case '\0': if (imverbose)
- {
- fprintf (stderr,
- " EOD encountered @ 0x%lx.\n",
- FTELL (infile) - 1L);
- }
- break; /* this kludge for non-standard files */
-
- case ',': startImage = FTELL (infile) - 1L;
- if (imverbose)
- {
- fprintf (stderr,
- ":::Processing image %d @ 0x%lx.\n",
- imageNum + 1, startImage);
- }
- myreadimage ();
- break;
-
- case ';': quit = TRUE;
- if (imverbose)
- {
- long currPos = FTELL (infile) - 1L;
- long diffPos;
-
- if (imverbose)
- fprintf (stderr,
- ":::GIF terminator @ 0x%lx.\n",
- currPos);
-
- FSEEK (infile, 0L, 2);
- if ((diffPos = FTELL (infile) - 1L - currPos) > 1L)
- {
- if (imverbose)
- fprintf (stderr,
- ":::%ld trailing extra bytes.\n",
- diffPos);
- }
- }
- break;
-
- case '!': if (imverbose)
- {
- fprintf (stderr,
- ":::Skipping extension @ 0x%lx.\n",
- FTELL (infile) - 1L);
- }
- readextension ();
- break;
-
- default: {
- char message[80];
-
- sprintf (message,
- "Illegal GIF block type (0x%x) @ 0x%lx.",
- ch, FTELL (infile) - 1L);
- fatal (message);
- break;
- }
- }
- } while (!quit);
- }
-
-
- static void
- initcolors (colortable, colormap, ncolors)
-
- char colortable[256][3];
- char colormap[256][3];
- int ncolors;
- {
- register
- i;
- char
- isColor = 0;
- int
- maxColor = 0;
-
- /*...Determine if image is grayscale; also, find maximum intensity...*/
-
- for (i = 0; i < ncolors; i++) {
- red[i] = colormap[i][0];
- green[i] = colormap[i][1];
- blue[i] = colormap[i][2];
-
- colortable[i][0] = colormap[i][0];
- colortable[i][1] = colormap[i][1];
- colortable[i][2] = colormap[i][2];
-
- if (rColors == RGRAYSCALE || imverbose)
- isColor |= ((red[i] != green[i]) ||
- (red[i] != blue[i]) ||
- (blue[i] != green[i] ));
-
- if (rNormalize /* != 0 */ || imverbose)
- {
- MAX_COLOR (red[i], green[i], blue[i]);
- }
- }
-
- /*...Convert from color to grayscale using NTSC algorithm...*/
-
- if (rColors == RGRAYSCALE)
- {
- if (isColor)
- {
- if (imverbose)
- fprintf (stderr, " Grayscaling color table.\n");
-
- maxColor = 0;
-
- for (i = 0; i < ncolors; i++)
- {
- GRAYSCALE_COLOR (red[i], green[i], blue[i]);
-
- if (rNormalize /* != 0 */ || imverbose)
- {
- MAX_INDEX (red[i]);
- }
- }
- }
- else
- {
- fprintf (stderr,
- " \"-g\" ignored: image is already grayscale.\n");
- }
- }
-
- /*...Re-scale the intensities...*/
-
- if (rNormalize /* != 0 */ && maxColor /* != 0 */)
- {
- if (rNormalize != maxColor)
- {
- int maxColor2 = maxColor >> 1;
-
- if (imverbose)
- fprintf (stderr,
- " Normalizing maximum color value from %d to %d.\n",
- maxColor, rNormalize);
-
- for (i = 0; i < ncolors; i++)
- {
- NORMALIZE_COLOR (red[i], green[i], blue[i]);
- }
- }
- else
- {
- if (imverbose)
- fprintf (stderr, " Maximum is normalization.\n");
- }
- }
-
- /*...Gamma correct the intensities...*/
-
- if (rGamma > 0.0)
- {
- int gamma[256];
- double gammaInv = (double) (1.0 / rGamma);
-
- if (imverbose)
- fprintf (stderr,
- " Adjusting color table with gamma %f.\n",
- rGamma);
-
- for (i = 0; i < 256; i++)
- {
- double pow ();
-
- gamma[i] = (int) (255.0 * pow ((double) ((float) i / 255.0),
- gammaInv)
- + 0.5);
- }
-
- for (i = 0; i < ncolors; i++)
- {
- GAMMA_CORRECT (red[i], green[i], blue[i]);
- }
- }
-
- if (imverbose)
- fprintf (stderr,
- " Image is %s with maximum single channel intensity %d.\n",
- isColor ? "color" : "grayscale", maxColor);
- }
-
-
- ImageStruct *
- readgifimage (fp, dirent)
-
- FILE *fp;
- FilenameStruct *dirent;
- {
- ImageStruct *im = (ImageStruct *) NULL;
- XImage *xim;
- long filesize;
-
-
- im = (ImageStruct *) malloc ((size_t) sizeof (ImageStruct));
- assert (im);
-
- fseek (fp, dirent->offset, 0);
-
- filesize = GetLong (fp); /* length of whole image file... */
-
- im->name = strtok (strdup (dirent->fname), ".");
- im->type = EXT_GIF;
- im->xoff = 0;
- im->yoff = 0;
-
- if ((infile = FOPEN (im->name, "rb")) == (MemoryFile *) NULL ||
- FSEEK (infile, filesize - 1L, SEEK_SET) /* != 0 */)
- {
- (void) FCLOSE (infile);
- error("%s: not enough memory to read gif file.\n", NULL);
- goto premature_exit;
- }
-
- if (fread (infile->buffer, filesize, 1, fp) != 1)
- {
- (void) FCLOSE (infile);
- error("%s: GIF data read failed\n", NULL);
- goto premature_exit;
- }
-
- (void) FSEEK (infile, 0L, SEEK_SET);
-
- if (checksignature () /* != 0 */)
- {
- (void) FCLOSE (infile);
- free (im->name);
- free ((char *) im);
- return (ImageStruct *) readimage (fp, dirent, EXT_PIC);
- }
-
- readscreen ();
-
- /*...Define global colormap...*/
-
- if (global)
- {
- unsigned long pmasks;
- u_long pixels[256];
- short i;
-
-
- im->cmaplen = 1 << globalbits;
-
- im->cmap = XCreateColormap (dsp, win, vis, AllocNone);
- XAllocColorCells (dsp, im->cmap, True, (unsigned long *) &pmasks,
- 0, (unsigned long *) pixels, im->cmaplen);
- for (i = 0; i < im->cmaplen; i++)
- {
- im->colors[i].pixel = pixels[i];
- im->colors[i].red = globalmap[i][0] << 8;
- im->colors[i].green = globalmap[i][1] << 8;
- im->colors[i].blue = globalmap[i][2] << 8;
- im->colors[i].flags = DoRed | DoGreen | DoBlue;
-
- if (imverbose) {
- printf("%02x%02x%02x ",
- im->colors[i].red >> 8,
- im->colors[i].green >> 8,
- im->colors[i].blue >> 8);
- if (!((i + 1) % 8))
- printf("\n");
- }
- }
-
- XStoreColors (dsp, im->cmap, im->colors, im->cmaplen);
- }
- else
- {
- im->cmap = (Colormap) NULL;
- im->cmaplen = 0;
- }
-
- process_loop ();
-
- (void) FCLOSE (infile);
-
- im->w = width;
- im->h = height;
- im->d = 8;
-
- xim = XCreateImage (dsp, vis, im->d, ZPixmap, 0, tempfile->buffer,
- im->w, im->h, 8, im->w);
- tempfile->buffer = (char *) NULL;
-
- #if 0
- im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8);
- XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h);
- XSync(dsp, False);
- #endif
-
- im->w = xim->width;
- im->h = xim->height;
- im->pix = (Pixmap) xim;
-
- (void) FCLOSE (tempfile);
- tempfile = (MemoryFile *) NULL;
-
- premature_exit:
-
- return im;
- }
-